import { Service } from 'egg';
import * as moment from 'moment';
import {OrderBy} from '../db/ordered_schedule';

export default class OrderedScheduleService extends Service {
    public async addByTimes(teacherId: number, studentId: number,
        dateStr: string, timeFrom: string, timeTo: string, times: number) {
        const date = moment(dateStr, 'YYYY-MM-DD');
        const newOrderedSchedules: any[] = [];
        for (let i = 0; i < times; ++i) {
            newOrderedSchedules.push({
                date: date.format('YYYY-MM-DD'),
                time_from: timeFrom,
                time_to: timeTo,
                teacher_id: teacherId,
                student_id: studentId,
            });
            date.add(7, 'days');
        }
        const { service } = this;

        // 检查每一个课程是否有冲突
        const mysql = this.app.mysql;
        const conn = await mysql.beginTransaction(); // 初始化事务
        try {
            // 绑定老师和学生的关系
            await service.admin.user.bindTeacher(studentId, teacherId);
            await service.admin.orderedSchedule.addAll(teacherId, newOrderedSchedules, conn);
            conn.commit();
        } catch (err) {
            conn.rollback();
            throw err;
        }
    }

    public async addAll(teacherId: number, studentSchedules: any[], conn: any) {
        const { service } = this;
        for (const ss of studentSchedules) {
            let day = moment(ss.date).day();
            if (day === 0) {
                // 星期天单独处理
                day = 7;
            }
            const timeFrom = ss.time_from;
            const timeTo = ss.time_to;
            const isValidate = await service.db.teacherSchedule.checkoutInTeacherSchedule(day, timeFrom, timeTo);
            if (!isValidate) {
                this.ctx.helper.invalidateParamsError('课程不在老师的排期之内，无法安排课程');
            }
        }

        const teacherOrderedSchedules = await service.db.orderedSchedule.getAllByTeacher(teacherId);

        for (const ss of studentSchedules) {
            for (const ts of teacherOrderedSchedules) {
                const tsDate = moment(ts.date).format('YYYY-MM-DD');
                if (tsDate === ss.date
                    && !(ts.time_from < ss.time_from && ts.time_to <= ss.time_from)
                    && !(ts.time_to > ss.time_to && ts.time_from >= ss.time_to)) {
                    this.ctx.helper.invalidateParamsError('排课时间冲突');
                }
            }
            await service.db.orderedSchedule.create(ss, conn);
        }
    }

    public async deleteAll(ids: number[]) {
        const { service } = this;
        if (!ids || ids.length <= 0) {
            return;
        }
        await Promise.all(ids.map((id) => service.db.orderedSchedule.removeOneById(id)));
    }

    public async getByDate(teacherIds: number[], startDate: string, endDate: string) {
        const result = await this.service.db.orderedSchedule.getByDate(teacherIds, startDate, endDate);
        if (!result) {
            return [];
        }
        const schedules: any[] = [];
        let curDate = '';
        let arrange: any = null;

        for (const r of result) {
            const date = moment(r.date).format('YYYY-MM-DD');
            if (curDate !== date) {
                curDate = date;
                arrange = [];
                schedules.push({
                    date,
                    arrange,
                });
            }
            const timeFrom = moment(r.time_from, 'HH:mm:SS').format('HH:mm');
            const timeTo = moment(r.time_to, 'HH:mm:SS').format('HH:mm');
            arrange.push({
                ...r,
                date,
                time_from: timeFrom,
                time_to: timeTo,
            });
        }
        return schedules;
    }

    public async getByPage(page: number, pageSize: number, orderBy: OrderBy,
        startDate?: string, endDate?: string, userId?: string) {
        const count = await this.service.db.orderedSchedule.getCount(startDate, endDate, userId);
        const data =
            await this.service.db.orderedSchedule.getByPage(page, pageSize, orderBy, startDate, endDate, userId);
        return {
            data,
            count,
            page,
            pageSize,
        };
    }
}
